package list.functions;

import java.util.List;

/**
 *
 * Fully Tested: No
 * Fully Documented: No
 * Created: 23-Apr-2012
 * Last Updated: 23-Apr-2012
 *
 * @param <T> 
 * @author Shimu Wu
 */
public class ComparableListFunctions<T extends Comparable<T>> {

    /**
     * Returns true if e1 is less than e2
     */
    public final Order<T> INCREASING = new Order<T>() {
        public boolean satisfyOrder(T e1, T e2) {
            return (e1.compareTo(e2) < 0);
        }        
    };
    
    /**
     * Returns true if e1 is less than or equal to e2
     */
    public final Order<T> NON_DECREASING = new Order<T>() {
        public boolean satisfyOrder(T e1, T e2) {
            return (e1.compareTo(e2) <= 0);
        }        
    };
    
    /**
     * Returns true if e1 is greater than e2
     */
    public final Order<T> DECREASING = new Order<T>() {
        public boolean satisfyOrder(T e1, T e2) {
            return (e1.compareTo(e2) > 0);
        }        
    };
    
    /**
     * Returns true if e1 is greater than or equal to e2
     */
    public final Order<T> NON_INCREASING = new Order<T>() {
        public boolean satisfyOrder(T e1, T e2) {
            return (e1.compareTo(e2) >= 0);
        }
    };
    
    public ComparableListFunctions(){        
    }
    
    /**
     * Returns the largest element in the list. The largest element 
     * is defined to be the element whose compareTo method returns a value
     * greater than or equal to 0 when called on all elements of the list.
     * If multiple elements exhibit this property, the first element
     * in the list that exhibit such property is returned (i.e. the 
     * element with the smallest index). 
     * 
     * @param <T>
     * @param list
     * @return 
     */
    public T max(List<T> list) {
        if (list.isEmpty()) {
            return null;
        }
        
        T max = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            if (max.compareTo(list.get(i)) < 0) {
                max = list.get(i);
            }
        }
        return max;
    }
    
    /**
     * Returns the smallest element in the list. The smallest element is 
     * defined to be the element whose compareTo method returns a value
     * less than or equal to 0 when called on all elements of the list.
     * If multiple elements exhibit this property, the first element
     * in the list that exhibit such property is returned (i.e. the 
     * element with the smallest index). 
     * 
     * @param list
     * @return 
     */
    public T min(List<T> list) {
        if (list.isEmpty()) {
            return null;
        }
        
        T min = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            if (min.compareTo(list.get(i)) > 0) {
                min = list.get(i);
            }
        }
        return min;
    }
    
    /**
     * Returns true if the given list is sorted in non-decreasing order
     * (i.e. A[i] less than or equal to A[i+1]).
     * 
     * @param list
     * @param order 
     * @return 
     */
    public boolean isSorted(List<T> list, Order<T> order) {
        if (list.size() < 2) {
            return true;
        }
        
        for (int i = 0; i < list.size() - 1; i++) {
            if (!order.satisfyOrder(list.get(i), list.get(i+1))) {
                return false;
            }
        }
        return true;
    }
}
